package com.pervasa.demo.re.impl.command;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;

import javax.swing.JOptionPane;
import javax.swing.JTextArea;

import com.pervasa.demo.re.impl.ReactivityEngine;
import com.pervasa.demo.re.impl.command.Token.Kind;
import com.pervasa.demo.re.impl.data.Action;
import com.pervasa.demo.re.impl.data.Condition;
import com.pervasa.demo.re.impl.data.Event;
import com.pervasa.demo.re.impl.data.Rule;

public class Executor {

	Map<String, String> basicEvents;
	Map<String, Event> eventList;
	Map<String, Condition> runtimeConditions;
	Map<String, Action> runtimeActions;
	Map<String, Rule> rules;
	JTextArea jTextArea2;
	Map<String, String> basicActions;
	ReactivityEngine re;
	int run;

	public Executor(ReactivityEngine reactivityEngine,
			Map<String, String> basicEvents,
			Map<String, Event> eventList,
			Map<String, Condition> runtimeConditions,
			Map<String, Action> runtimeActions, Map<String, Rule> rules,
			Map<String, String> basicActions, int run, JTextArea jTextArea2) {

		this.re = reactivityEngine;
		this.basicEvents = basicEvents;
		this.eventList = eventList;
		this.runtimeActions = runtimeActions;
		this.runtimeConditions = runtimeConditions;
		this.basicActions = basicActions;
		this.rules = rules;
		this.jTextArea2 = jTextArea2;
		this.run = run;
	}

	public void exeList() {

		StringBuffer str1 = new StringBuffer();
		String str5;
		Event a;

		str1.append("\n----BASIC EVENTS----\n");

		for (Map.Entry<String, String> e : basicEvents.entrySet()) {
			str1.append(e.getValue() + "\n");

		}
		str1.append("\n----BASIC ACTIONS----\n");

		for (Map.Entry<String, String> p : basicActions.entrySet()) {
			str1.append(p.getValue() + "\n");
		}

		str1.append("\n----USER DEFINED EVENTS----\n");

		for (Map.Entry<String, Event> e : eventList.entrySet()) {
			str5 = e.getKey();
			a = e.getValue();
			str1.append(str5 + "=" + a.getExpression() + "\n");
		}

		Condition print;

		str1.append("\n----SET CONDITIONS----\n");
		for (Map.Entry<String, Condition> e : runtimeConditions.entrySet()) {
			print = e.getValue();
			str1.append(e.getKey() + "=" + print.value + "\n");
		}
		Action apo;
		str1.append("\n----USER DEFINED ACTIONS----\n");
		for (Map.Entry<String, Action> e : runtimeActions.entrySet()) {
			apo = e.getValue();
			str1.append(e.getKey() + "=" + apo.getExpression() + "\n");
		}
		Rule rpo;
		str1.append("\n----DEFINED RULES----\n");
		for (Map.Entry<String, Rule> e : rules.entrySet()) {
			rpo = e.getValue();
			str1.append(rpo + "\n");
		}

		String str3 = str1 + "\n";

		if (jTextArea2 == null) {
			System.out.println("LALA");
		}
		jTextArea2.setText(str3);
	}

	public void exeList(Kind listType) {

		StringBuffer str1 = new StringBuffer();
		String str5;
		Event a;

		if (listType.toString() == Kind.EVENT.toString()) {
			str1.append("\n----BASIC EVENTS----\n");

			for (Map.Entry<String, String> e : basicEvents.entrySet()) {
				str1.append(e.getValue() + "\n");

			}
			str1.append("\n----USER DEFINED EVENTS----\n");
			for (Map.Entry<String, Event> e : eventList.entrySet()) {
				str5 = e.getKey();
				a = e.getValue();
				str1.append(str5 + "=" + a.getExpression() + "\n");

			}
		} else if (listType.toString() == Kind.CONDITION.toString()) {
			Condition print;
			str1.append("\n----SET CONDITIONS----\n");
			for (Map.Entry<String, Condition> e : runtimeConditions.entrySet()) {
				print = e.getValue();
				str1.append(e.getKey() + "=" + print.value + "\n");
			}
		} else if (listType.toString() == Kind.ACTION.toString()) {
			Action app;

			str1.append("\n----BASIC ACTIONS----\n");

			for (Map.Entry<String, String> p : basicActions.entrySet()) {
				str1.append(p.getValue() + "\n");
			}

			str1.append("\n----USER DEFINED ACTIONS----\n");
			for (Map.Entry<String, Action> e : runtimeActions.entrySet()) {
				app = e.getValue();
				str1.append(e.getKey() + "=" + app.getExpression() + "\n");
			}
		} else if (listType.toString() == Kind.RULE.toString()) {
			Rule rp;
			str1.append("\n----USER DEFINE RULES----\n");
			for (Map.Entry<String, Rule> e : rules.entrySet()) {
				rp = e.getValue();
				str1.append(rp + "\n");
			}
		} else {
			JOptionPane.showMessageDialog(re, "Invalid usage of List");
			return;
		}
		String str3 = str1 + "\n";
		jTextArea2.setText(str3);

	}

	public void exeBasic() {
		
		StringBuffer str4 = new StringBuffer();
		str4.append("\n\n\n----BASIC EVENTS----\n");
		for (Map.Entry<String, String> e : basicEvents.entrySet()) {
			str4.append(e.getValue() + "\n");

		}
		str4.append("\n\n\n----BASIC ACTIONS----\n");
		for (Map.Entry<String, String> p : basicActions.entrySet()) {
			str4.append(p.getValue() + "\n");
		}
		String str6 = str4 + "\n";
		jTextArea2.setText(str6);
	}

	public void exeBasic(Kind cmd) {
		StringBuffer str4 = new StringBuffer();

		if (cmd == Kind.EVENT) {
			str4.append("\n\n\n----BASIC EVENTS----\n");
			for (Map.Entry<String, String> e : basicEvents.entrySet()) {
				str4.append(e.getValue() + "\n");

			}
		} else if (cmd == Kind.ACTION) {
			for (Map.Entry<String, String> p : basicActions.entrySet()) {
				str4.append("\n\n\n----BASIC ACTIONS----\n");
				str4.append(p.getValue() + "\n");
			}
		} else {
			JOptionPane.showMessageDialog(re, "Invalid usage of BASIC");
			return;
		}
		String str6 = str4 + "\n";
		jTextArea2.setText(str6);
	}

	public void exeDefine(String name, Condition condition) {
		runtimeConditions.put(name, condition);
	}

	public void exeDefine(String name, Action action) {
		runtimeActions.put(name, action);
	}

	public void exeDefine(String name, Rule rule) {
		rules.put(name, rule);
	}

	public void exeDefine(String name, Event event) {
		eventList.put(name, event);
	}
	
	public void exeSet(String condName, Kind flag) {

		/*
		 * String trimString=str.trim(); char c[]=str.toCharArray();
		 * StringBuffer str7=new StringBuffer(); StringBuffer str8=new
		 * StringBuffer(); int i=0; while(c[i]!=' ') { i++; } i++;
		 * while(c[i]!='=') {
		 * 
		 * str7.append(c[i]); System.out.println(str7); i++;
		 * 
		 * } i++; for(;i<(str.length());i++) { str8.append(c[i]);
		 * System.out.println(str8); }
		 * 
		 * 
		 * String str9=str7+""; String str10=str8+"";
		 */

		// String condclass[] = cond[0].split("\\s"); // condName

		String chk;

		int check = 0;
		for (Map.Entry<String, Condition> e : runtimeConditions.entrySet()) {
			chk = e.getKey();

			// TODO this possible has error, change .matches to .equal
			if (condName.equals(chk)) {
				check = 1;
				break;
			}
		}

		if (check == 1) {
			if (flag == Kind._TRUE) {
				Condition a = new Condition(condName, true);
				runtimeConditions.put(condName, a);
			}

			else if (flag == Kind._FALSE) {
				Condition a1 = new Condition(condName, false);
				runtimeConditions.put(condName, a1);
			} else {
				JOptionPane
						.showMessageDialog(re,
								"Condition variable can accept only either true or false");
				return;
			}
		} else {
			JOptionPane.showMessageDialog(re,
					"Condition variable not present,please define it first");
			return;
		}

	}

	public void exeRun() {
		System.out.println("TotalMemory: " + Runtime.getRuntime().totalMemory());
		System.out.println("FreeMemory: " + Runtime.getRuntime().freeMemory());
		if (re.getRun() == 1) {
			JOptionPane.showMessageDialog(re, "RUN mode is already on");
			return;
		} else {
			re.setRun(1);
		}
		// System.out.println(run);
	}

	public void exeStop() {
		System.out.println("TotalMemory: " + Runtime.getRuntime().totalMemory());
		System.out.println("FreeMemory: " + Runtime.getRuntime().freeMemory());
		if (re.getRun() == 0) {
			JOptionPane.showMessageDialog(re, "RUN mode already off");
			return;
		} else {
			re.setRun(0);
		}
		// System.out.println(run);
	}

	public void exeLoad(String filePath) throws SyntaxException {
		try {
			BufferedReader input = new BufferedReader(new FileReader(new File(filePath)));
			while (input.ready()) {
				Parser parser = new Parser(input.readLine(), re, this);
				parser.parse();
			}
			input.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void exeClear() {
		jTextArea2.setText(" ");
	}
}
